package top.dreamcenter.rss.rsssolverweb.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.StringUtils;
import top.dreamcenter.rss.rsssolverprotocal.SpiderTemplate;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 从plugins目录装载插件
 */
@Slf4j
public class PluginLoader {
    /**
     * 插件文件夹位置
     */
    private static final String PLUGIN_DIR = "plugins";
    /**
     * 插件META-INF配置文件
     */
    private static final String PLUGIN_CONFIG = "META-INF/rss_spider";

    private final Map<String, List<String>> cache = new ConcurrentHashMap<>();

    /**
     * 装载插件
     * @return
     * @throws Exception
     */
    public Set<Class<?>> loadPlugins() throws Exception {

        // 查看插件文件夹是否存在
        File pluginDir = new File(PLUGIN_DIR);
        if (!pluginDir.exists()) {
            throw new RuntimeException("Plugin directory does not exist: " + PLUGIN_DIR);
        }

        // 加载plugins下的所有jar包
        Set<URL> urls = new HashSet<>();
        File[] jarFiles = pluginDir.listFiles();
        if (jarFiles != null) {
            for (File file : jarFiles) {
                if (file.isFile() && file.getName().endsWith(".jar")) {
                    urls.add(file.toURI().toURL());
                }
            }
        }

        // 将jar包资源全部加入到当前ClassLoader
        URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), getClass().getClassLoader());
        Enumeration<URL> plugins = classLoader.getResources(PLUGIN_CONFIG);

        // 从jar包解析需要注册的插件
        while (plugins.hasMoreElements()) {
            URL plugin = plugins.nextElement();
            UrlResource resource = new UrlResource(plugin);
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            for (Map.Entry<?, ?> entry : properties.entrySet()) {
                String configKey = ((String) entry.getKey()).trim();
                String[] configValues =
                        StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
                for (String value : configValues) {
                    cache.computeIfAbsent(configKey, key -> new ArrayList<>())
                            .add(value.trim());
                }
            }
        }
        log.info("Plugins loaded: " + cache);

        // 将需要注册的插件进行类加载
        Set<Class<?>> classes = new HashSet<>();
        List<String> list = cache.get("plugins");
        for (String pluginName : list) {
            Class<?> clazz = Class.forName(pluginName, true, classLoader);
            if (SpiderTemplate.class.isAssignableFrom(clazz) ) {
                classes.add(clazz);
            }
        }

        return classes;
    }
}
